/*
 * Licensed Materials - Property of tenxcloud.com
 * (C) Copyright 2018 TenxCloud. All Rights Reserved.
 * 2018-06-13  @author lizhen
 */

package middleware

import (
	"github.com/gin-gonic/gin"
	"github.com/golang/glog"
	"github.com/hashicorp/golang-lru"
	"github.com/jinzhu/gorm"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"modules.tenxcloud.com/common/composite"
	"modules.tenxcloud.com/common/model/cluster"
	commonerr "modules.tenxcloud.com/common/utility/errors"
	"net/http"
)

const (
	ClusterInfoKey = "cluster-info"
)

var (
	// TODO: data in tenx_clusters considered stable, so for there is no refreshing logic
	cache, _ = lru.New(2)
)

func ClusterInfo(getClusterID func(*gin.Context) string) func(*gin.Context) {
	return func(c *gin.Context) {
		clusterID := getClusterID(c)
		if ci, exist := cache.Get(clusterID); exist {
			c.Set(ClusterInfoKey, ci)
			c.Next()
			return
		}
		db, err := composite.Database.GetOrm()
		if err != nil {
			glog.Errorf("get database connection failed, %s", err)
			c.AbortWithStatusJSON(commonerr.InternalServerError(err))
			return
		}
		cm, err := cluster.FindOneByClusterID(clusterID, db)
		if err != nil {
			glog.Warningf("get cluster info from db failed, cluster id %s, %s", clusterID, err)
			if gorm.IsRecordNotFoundError(err) {
				c.AbortWithStatusJSON(commonerr.NotFound(&errors.StatusError{
					ErrStatus: metav1.Status{
						Status: metav1.StatusFailure,
						Reason: metav1.StatusReasonNotFound,
						Code:   http.StatusNotFound,
						Details: &metav1.StatusDetails{
							Causes: []metav1.StatusCause{{
								Type:  metav1.CauseTypeFieldValueNotFound,
								Field: "clusterId",
							}},
						},
					},
				}))
				return
			}
			c.AbortWithStatusJSON(commonerr.InternalServerError("get cluster info from db failed"))
			return
		}
		cache.Add(clusterID, cm)
		c.Set(ClusterInfoKey, cm)
		c.Next()
	}
}
